package icu.zhhll.util.codec;

import icu.zhhll.util.lang.HexUtils;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.spec.InvalidKeySpecException;

/**
 * DES算法加解密
 *
 * @author zh
 * @date 2023/8/5 21:26
 */
public class DesUtils {

    private static final String DES = "DES";

    private static final String DEFAULT_KEY = "zhDes001";

    /**
     * 加密
     *
     * @param content
     * @return
     */
    public static String encrypt(String content) {
        return encrypt(content, DEFAULT_KEY);
    }

    public static String encrypt(String content, String key) {
        if (StringUtils.isBlank(key) || key.length() < 8) {
            throw new CodecException("DES_KEY长度至少8位");
        }

        return HexUtils.bytesToHexString(encrypt(content.getBytes(), key.getBytes()));

    }

    /**
     * 加密
     *
     * @param src 数据源
     * @param key 密钥，长度至少8
     * @return 返回加密后的数据
     * @throws Exception
     */
    private static byte[] encrypt(byte[] src, byte[] key) {
        // DES算法要求有一个可信任的随机数源
        SecureRandom sr = new SecureRandom();
        // 从原始密匙数据创建DESKeySpec对象
        DESKeySpec dks;
        try {
            dks = new DESKeySpec(key);
            // 创建一个密匙工厂，然后用它把DESKeySpec转换成一个SecretKey对象
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
            SecretKey securekey = keyFactory.generateSecret(dks);
            // Cipher对象实际完成加密操作
            Cipher cipher = Cipher.getInstance(DES);
            // 用密匙初始化Cipher对象
            cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
            // 现在，获取数据并加密正式执行加密操作
            return cipher.doFinal(src);
        } catch (InvalidKeyException | NoSuchAlgorithmException | InvalidKeySpecException |
                BadPaddingException | IllegalBlockSizeException | NoSuchPaddingException e) {
            throw new CodecException("加密失败", e);
        }

    }

    /**
     * 加密
     *
     * @param content
     * @return
     */
    public static String decrypt(String content) {
        return decrypt(content, DEFAULT_KEY);
    }

    public static String decrypt(String content, String key) {
        if (StringUtils.isBlank(key) || key.length() < 8) {
            throw new RuntimeException("DES_KEY长度至少8位");
        }

        return new String(decrypt(HexUtils.hexStringToBytes(content), key.getBytes()));

    }

    /**
     * 解密
     *
     * @param src 数据源
     * @param key 密钥，长度必须是8的倍数
     * @return 返回解密后的原始数据
     * @throws Exception
     */
    private static byte[] decrypt(byte[] src, byte[] key) {
        try {
            // DES算法要求有一个可信任的随机数源
            SecureRandom sr = new SecureRandom();
            // 从原始密匙数据创建一个DESKeySpec对象
            DESKeySpec dks = new DESKeySpec(key);
            // 创建一个密匙工厂，然后用它把DESKeySpec对象转换成一个SecretKey对象
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance(DES);
            SecretKey securekey = keyFactory.generateSecret(dks);
            // Cipher对象实际完成解密操作
            Cipher cipher = Cipher.getInstance(DES);
            // 用密匙初始化Cipher对象
            cipher.init(Cipher.DECRYPT_MODE, securekey, sr);
            // 现在，获取数据并解密正式执行解密操作
            return cipher.doFinal(src);
        } catch (InvalidKeyException | NoSuchAlgorithmException | InvalidKeySpecException | NoSuchPaddingException
                | BadPaddingException | IllegalBlockSizeException e) {
            throw new CodecException("解密失败", e);
        }

    }
}
